/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2024-05-08     liuchao       the first version
 */
#define LOG_TAG "sensor"
#include "ulog.h"
#include "drv_sensor.h"
#include "configuration.h"
#include <drv_relay.h>

#define ADC_DEV_NAME "adc1"

static rt_adc_device_t dev = NULL;
// static rt_mutex_t sensor_mutex = NULL;

rt_uint32_t sensor_value(sensor_e sensor)
{
    rt_uint32_t ret = 0;
    if (sensor >= SENSOR_START && sensor < SENSOR_END)
    {
        // rt_mutex_take(sensor_mutex, RT_WAITING_FOREVER);
        ret = rt_adc_read(dev, sensor);
        // rt_mutex_release(sensor_mutex);
    }
    else
    {
        LOG_E("Invalid channel %d", sensor);
    }
    return ret;
}

configuration_e sensor_to_configuration(sensor_e sensor)
{
    configuration_e ret = CONFIGRATION_END;
    switch (sensor)
    {
    // 油压
    case SENSOR_OIL_PRESSURE:
        ret = CONFIGURATION_SENSOR_OIL_PRESSURE_BASELINE;
        break;
        // 油缸位移
    case SENSOR_PUTTER_DISTANCE:
        ret = CONFIGURATION_SENSOR_PUTTER_DISTANCE_BASELINE;
        break;
        // 齿轮位移
    case SENSOR_GEAR_DISTANCE:
        ret = CONFIGURATION_SENSOR_GEAR_DISTANCE_BASELINE;
        break;
        // 油温
    case SENSOR_OIL_TEMP:
        ret = CONFIGURATION_SENSOR_OIL_TEMP_BASELINE;
        break;
        // 油量
    case SENSOR_OIL_VOLUME:
        ret = CONFIGURATION_SENSOR_OIL_VOLUME_BASELINE;
        break;
        // 油压2
    case SENSOR_OIL_PRESSURE_2:
        ret = CONFIGURATION_SENSOR_OIL_PRESSURE_2_BASELINE;
        break;
    default:
        break;
    }
    return ret;
}

float sensor_voltage(sensor_e sensor)
{
    rt_uint32_t sum = 0;
    for (int i = 0; i < 100; i++)
    {
        sum += sensor_value(sensor);
    }
    if (sensor == SENSOR_BATTERY)
    {
        float ret = sum / 100.0;
        return ret * 0.01653;
    }
    rt_uint32_t baseline = configuration_get_uint32(sensor_to_configuration(sensor));
    float ret = sum / 100.0;
    return (ret / baseline) * 5.0;
}

void sensor_calibrate(sensor_e sensor)
{
    if (sensor < SENSOR_START || sensor >= SENSOR_END)
    {
        LOG_E("Invalid sensor %d", sensor);
        return;
    }
    rt_uint32_t sum = 0;
    for (int i = 0; i < 100; i++)
    {
        sum += sensor_value(sensor);
    }
    configuration_e configuration = sensor_to_configuration(sensor);
    configuration_set_uint32(configuration, sum / 100);
    LOG_I("Sensor %d, configuration: %s, calibratd: %lu", sensor, configuration_name(configuration), sum / 100);
}

const char* sensor_name(sensor_e sensor)
{
    switch (sensor)
    {
    // 油压
    case SENSOR_OIL_PRESSURE:
        return "OIL_PRESSURE";
        // 油缸位移
    case SENSOR_PUTTER_DISTANCE:
        return "PUTTER_DISTANCE";
        // 齿轮位移
    case SENSOR_GEAR_DISTANCE:
        return "GEAR_DISTANCE";
        // 油温
    case SENSOR_OIL_TEMP:
        return "OIL_TEMP";
        // 油量
    case SENSOR_OIL_VOLUME:
        return "OIL_VOLUME";
    case SENSOR_BATTERY:
        return "BATTERY";
        // 油压2
    case SENSOR_OIL_PRESSURE_2:
        return "OIL_PRESSURE_2";
    default:
        return "UNKNOWN";
    }
}

float voltage_to_axial(float voltage)
{
    float k = configuration_get_float(CONFIGURATION_AXIAL_K);
    float b = configuration_get_float(CONFIGURATION_AXIAL_B);
    return (voltage * k) + b;
}

static float s_axial[SENSOR_END];
static rt_mutex_t s_axial_mutex = NULL;
float sensor_axial(sensor_e sensor)
{
    float ret = 0;
    rt_mutex_take(s_axial_mutex, RT_WAITING_FOREVER);
    if (relay_state(RELAY_PERIPH_PWR) == RELAY_STATE_ON)
    {
        s_axial[sensor] = voltage_to_axial(sensor_voltage(sensor));
    }
    ret = s_axial[sensor];
    rt_mutex_release(s_axial_mutex);
    return ret;
}
static float s_distance[SENSOR_END];
static rt_mutex_t s_distance_mutex = NULL;
float sensor_distance(sensor_e sensor)
{
    float ret = 0;
    rt_mutex_take(s_distance_mutex, RT_WAITING_FOREVER);
    if (relay_state(RELAY_PERIPH_PWR) == RELAY_STATE_ON)
    {
        if (sensor == SENSOR_PUTTER_DISTANCE)
        {
            s_distance[sensor] = (sensor_voltage(sensor) / 5.0) * 200.0;
        }
        else if (sensor == SENSOR_GEAR_DISTANCE)
        {
            s_distance[sensor] = (sensor_voltage(sensor) / 5.0) * 25.0;
        }
        else
        {
            s_distance[sensor] = 0;
        }
    }
    ret = s_distance[sensor];
    rt_mutex_release(s_distance_mutex);
    return ret;
}

float sensor_oil_volume(sensor_e sensor)
{
    float ret = 0;
    if (sensor == SENSOR_OIL_VOLUME)
    {
        rt_uint32_t v = sensor_value(sensor);
        ret = (v * 100.0) / 600.0;
    }
    return ret;
}

static int sensor_init()
{
    s_axial_mutex = rt_mutex_create("axial", RT_IPC_FLAG_PRIO);
    s_distance_mutex = rt_mutex_create("distance", RT_IPC_FLAG_PRIO);
    dev = (rt_adc_device_t) rt_device_find(ADC_DEV_NAME);
    rt_adc_enable(dev, 1);
    for (int channel = SENSOR_START; channel < SENSOR_END; channel++)
    {
        rt_adc_enable(dev, channel);
    }
    return RT_EOK;
}
INIT_COMPONENT_EXPORT(sensor_init);
